#pragma once

#include "config.h"
#include "pipeline.h"

#include <memory>
#include <optional>
#include <string>
#include <vector>

/**
 * @file configweave.h
 * @brief ConfigWeave 外观类头文件，提供组装并运行配置流水线的高层 API
 * @details 通过统一的外观接口，您可以：
 * - 使用 `from_file` 添加单文件读取 provider；
 * - 使用 `normalize_keys` 统一键名风格；
 * - 使用 `require_key` 校验必填键；
 * - 通过 `add_transformer/add_validator/add_sink` 扩展流水线；
 * - 调用 `run` 执行并返回只读根与错误集合。
 */
namespace cfg
{

/**
 * @brief ConfigWeave 外观类
 * @details 提供易用的高层 API 来组装并运行配置流水线。
 * 设计约定：
 * - 函数名小写、下划线分割；
 * - 参数与数据成员小写、下划线分割；
 * - 类型大写驼峰；
 * - 最小接口集：from_file/normalize_keys/require_key/add_* 与 run。
 */
class ConfigWeave
{
public:
    // 便捷：子校验器描述（名称 + 选项）
    struct SubValidator
    {
        std::string name;
        PluginOptions options;
    };
    /**
     * @brief 流水线执行结果快照
     * @details 承载只读根与错误集合，并提供便捷视图与读取接口。
     */
    struct Result
    {
        /// 只读根对象（可能为空）
        std::shared_ptr<const Object> root;
        /// 执行过程中产生的错误集合
        std::vector<ConfigError> errors;

        /**
         * @brief 结果是否无错误且存在有效根
         */
        bool ok() const noexcept;

        /**
         * @brief 创建只读根视图
         * @return 若 `root` 为空则返回空视图（current=nullptr）
         */
        View view() const;

        /**
         * @brief 便捷读取整型配置
         * @param path 路径（支持 JSON Pointer 与 a.b[0].c 语法）
         * @return 成功返回值，失败返回 `unexpected(ConfigError)`
         */
        expected<int64_t, ConfigError> get_int64(std::string_view path) const;

        /**
         * @brief 便捷读取数值配置
         * @param path 路径
         * @return 成功返回值，失败返回 `unexpected(ConfigError)`
         */
        expected<double, ConfigError> get_number(std::string_view path) const;

        /**
         * @brief 便捷读取字符串配置
         * @param path 路径
         * @return 成功返回值，失败返回 `unexpected(ConfigError)`
         */
        expected<std::string, ConfigError> get_string(std::string_view path) const;

        /**
         * @brief 便捷读取布尔配置
         * @param path 路径
         * @return 成功返回值，失败返回 `unexpected(ConfigError)`
         */
        expected<bool, ConfigError> get_bool(std::string_view path) const;
    };

    /**
     * @brief 添加单文件 provider（"single_file"），从 `path` 读取并 include
     * @param path 文件路径（支持 YAML/JSON）
     * @return 返回 `ConfigWeave&` 以支持链式调用
     */
    ConfigWeave & from_file(std::string path);

    /**
     * @brief 添加键规整 transformer（"normalize_keys"）
     * @param style 规整风格（如 `lowercase`、`snake_case`）
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & normalize_keys(std::string style = "lowercase");

    /**
     * @brief 添加必填键 validator（"required_key"）
     * @param path 必填键路径
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & require_key(std::string path);

    /**
     * @brief 添加数值范围校验器（"number_in_range"）
     * @param path 路径（支持 JSON Pointer 与 a.b[0].c 语法）
     * @param min 最小值（可选）
     * @param max 最大值（可选）
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & number_in_range(std::string path,
                                  std::optional<double> min = std::nullopt,
                                  std::optional<double> max = std::nullopt,
                                  std::optional<double> default_value = std::nullopt);

    /**
     * @brief 添加枚举集合包含校验器（"enum_in_set"）
     * @param path 路径
     * @param values 允许的枚举值集合（将以逗号拼接传递给插件）
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & enum_in_set(std::string path,
                              std::vector<std::string> values,
                              std::optional<std::string> default_value = std::nullopt);

    /**
     * @brief 添加数组长度范围校验器（"array_length"）
     * @param path 路径
     * @param min_len 最短长度（可选）
     * @param max_len 最长长度（可选）
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & array_length(std::string path,
                               std::optional<size_t> min_len = std::nullopt,
                               std::optional<size_t> max_len = std::nullopt);

    /**
     * @brief 添加对象必需键集合校验器（"object_required_keys"）
     * @param path 路径
     * @param keys 需要存在的键集合（将以逗号拼接传递给插件）
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & object_required_keys(std::string path, std::vector<std::string> keys);

    // 新增通用校验器便捷方法（C++17 实现）
    /**
     * @brief 添加严格最小值校验（"exclusive_minimum"）
     * @param path 路径（数值）
     * @param minimum 最小值（目标必须严格大于该值）
     */
    ConfigWeave & exclusive_minimum(std::string path, double minimum);

    /**
     * @brief 添加严格最大值校验（"exclusive_maximum"）
     * @param path 路径（数值）
     * @param maximum 最大值（目标必须严格小于该值）
     */
    ConfigWeave & exclusive_maximum(std::string path, double maximum);

    /**
     * @brief 添加数组唯一性校验（"unique_items"）
     * @param path 路径（数组）
     */
    ConfigWeave & unique_items(std::string path);

    /**
     * @brief 添加数组包含项校验（"contains"）
     * @param path 路径（数组）
     * @param value 期望包含的标量值（按字符串比较）
     */
    ConfigWeave & contains(std::string path, std::string value);

    /**
     * @brief 添加依赖必填校验（"dependent_required"）
     * @param path 对象路径
     * @param key 触发键（存在时检查依赖）
     * @param requires 依赖键集合（以逗号拼接传递）
     */
    ConfigWeave &
    dependent_required(std::string path, std::string key, std::vector<std::string> requiress);

    // 组合校验器便捷方法（对应 validators_combinators.cpp）
    /**
     * @brief 添加“全部满足”组合校验器（"all_of"）
     * @param subs 子校验器列表，所有子校验器必须全部通过
     * @return 返回 `ConfigWeave&` 以支持链式调用
     */
    ConfigWeave & all_of(const std::vector<SubValidator> & subs);

    /**
     * @brief 添加“任一满足”组合校验器（"any_of"）
     * @param subs 子校验器列表，至少一个子校验器通过即可
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & any_of(const std::vector<SubValidator> & subs);

    /**
     * @brief 添加“唯一满足”组合校验器（"one_of"）
     * @param subs 子校验器列表，有且仅有一个子校验器通过
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & one_of(const std::vector<SubValidator> & subs);

    /**
     * @brief 添加“非”逻辑校验器（"not"）
     * @param sub 被取反的子校验器
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & not_(const SubValidator & sub);

    /**
     * @brief 添加“条件分支”组合校验器（"if_then_else"）
     * @param if_sub 条件子校验器
     * @param then_sub then 子校验器（可选），当 if_sub 通过时执行
     * @param else_sub else 子校验器（可选），当 if_sub 未通过时执行
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & if_then_else(const SubValidator & if_sub,
                               std::optional<SubValidator> then_sub = std::nullopt,
                               std::optional<SubValidator> else_sub = std::nullopt);

    /**
     * @brief 添加任意 transformer（扩展点）
     * @param name 插件名称
     * @param options 插件选项
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & add_transformer(std::string name, PluginOptions options = {});

    /**
     * @brief 添加任意 validator（扩展点）
     * @param name 插件名称
     * @param options 插件选项
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & add_validator(std::string name, PluginOptions options = {});

    /**
     * @brief 添加一个 sink（如写文件/打印）
     * @param name 插件名称
     * @param options 插件选项
     * @return 返回 `ConfigWeave&`
     */
    ConfigWeave & add_sink(std::string name, PluginOptions options = {});

    /**
     * @brief 运行流水线，返回结果快照
     * @return `Result` 包含只读根与错误集合
     */
    [[nodiscard]] Result run() const;

private:
    /// 已配置的 providers
    std::vector<ProviderSpec> _providers;

    /// 已配置的 transformers
    std::vector<TransformerSpec> _transformers;

    /// 已配置的 validators
    std::vector<ValidatorSpec> _validators;

    /// 已配置的 sinks
    std::vector<SinkSpec> _sinks;
};

} // namespace cfg
